package com.wxm.jwt.util;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.wxm.jwt.exception.JWTErrorCode;
import com.wxm.jwt.exception.JWTException;
import io.jsonwebtoken.*;

import java.security.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;

/**
 * <p>
 *
 * </p>
 *
 * @author: wxm
 * @Date: 2021/10/6
 */
public class JwtHelper {

    /**
     * 解析token
     * @param token Token字符串
     * @param publicKey 公钥
     * @param tClass 期待解析出的类型
     * @param <T> T
     * @return JwtUserInfo
     */
    public static <T> T getJwtFromToken(String token, PublicKey publicKey,Class<T> tClass) {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();

        JSONObject jsonObject = new JSONObject();
        for (Map.Entry<String, Object> entry : body.entrySet()) {
            jsonObject.put(entry.getKey(),entry.getValue());
        }
        return jsonObject.toJavaObject(tClass);
    }

    /**
     * 生成Token
     * @param jsonUser Token存储的用户信息
     * @param priKey 私钥
     * @param second 有效期 秒
     * @return String
     */
    public static String generateToken(JSONObject jsonUser, PrivateKey priKey,Integer second){
        LocalDateTime localDateTime = LocalDateTime.now().plusSeconds(second);
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        JwtBuilder jwtBuilder = Jwts.builder();
        for (Map.Entry<String, Object> entry : jsonUser.entrySet()) {
            jwtBuilder.claim(entry.getKey(),entry.getValue());
        }

        //设置过期时间
        jwtBuilder.setExpiration(date);
        //设置加密算法RS256
        jwtBuilder.signWith(SignatureAlgorithm.RS256,priKey);
        //将jwt3部分进行拼接 返回
        return jwtBuilder.compact();
    }

    /**
     * 公钥解析token
     * @param token Token
     * @param pubKeyPath 公钥字节数组
     * @return Jws<Claims>
     */
    private static Jws<Claims> parserToken(String token, PublicKey pubKeyPath){
        try {
            return Jwts.parser().setSigningKey(pubKeyPath).parseClaimsJws(token);
        } catch (ExpiredJwtException ex) {
            //过期
            JWTException.error(JWTErrorCode.JWT_TOKEN_EXPIRED.getCode(), JWTErrorCode.JWT_TOKEN_EXPIRED.getMsg());
        } catch (IllegalArgumentException ex) {
            //token 为空
            JWTException.error(JWTErrorCode.JWT_ILLEGAL_ARGUMENT.getCode(), JWTErrorCode.JWT_ILLEGAL_ARGUMENT.getMsg());
        } catch (Exception e) {
            JWTException.error(JWTErrorCode.JWT_PARSER_TOKEN_FAIL.getCode(), JWTErrorCode.JWT_PARSER_TOKEN_FAIL.getMsg());
        }
        return null;
    }

    /**
     * 生成公钥和私钥到E盘
     * @throws NoSuchAlgorithmException
     */
    private static void creatKey() throws NoSuchAlgorithmException {
        //自定义 随机密码,  请修改这里
        String password = "key";

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(password.getBytes());
        keyPairGenerator.initialize(1024, secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();

        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();

        FileUtil.writeBytes(publicKeyBytes, "E:\\pub.key");
        FileUtil.writeBytes(privateKeyBytes, "E:\\pri.key");
    }
}
